package com.ziytek.web.citizen.service.impl;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ziytek.web.citizen.caffeine.CachePutOrGet;
import com.ziytek.web.citizen.config.ConfigInit;
import com.ziytek.web.citizen.config.caffeine.CaffeineUtil;
import com.ziytek.web.citizen.constant.JobConstant;
import com.ziytek.web.citizen.constant.NumConstant;
import com.ziytek.web.citizen.constant.ServerConstant;
import com.ziytek.web.citizen.enums.ErrorTypeEnum;
import com.ziytek.web.citizen.enums.StepTypeNoEnum;
import com.ziytek.web.citizen.event.CommandFirstDataEvent;
import com.ziytek.web.citizen.event.CommandIssuedEndEvent;
import com.ziytek.web.citizen.event.CommandIssuedSuccessEvent;
import com.ziytek.web.citizen.event.WholeCommandIssuedEvent;
import com.ziytek.web.citizen.exception.IssuedException;
import com.ziytek.web.citizen.mapper.BasicStepSettingsMapper;
import com.ziytek.web.citizen.mapper.CommandIssuedMapper;
import com.ziytek.web.citizen.mapper.OperationDetailMapper;
import com.ziytek.web.citizen.mapper.SettingDetailMapper;
import com.ziytek.web.citizen.model.bean.AddSettings;
import com.ziytek.web.citizen.model.bean.CommandIssuedSuccess;
import com.ziytek.web.citizen.model.req.StepSettingsIssuedSingleReq;
import com.ziytek.web.citizen.model.rsp.R;
import com.ziytek.web.citizen.quartz.QuartzService;
import com.ziytek.web.citizen.service.*;
import com.ziytek.web.citizen.service.itf.StepSettingsIssuedSingleService;
import com.ziytek.web.citizen.util.CabinetNoUtil;
import com.ziytek.web.citizen.util.KeyUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * @author fengh
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class StepSettingsIssuedSingleServiceImpl implements StepSettingsIssuedSingleService {

    private final Gson gson;
    private final ConfigInit configInit;
    private final CachePutOrGet cachePutOrGet;
    private final QuartzService quartzService;
    private final ApplicationContext context;
    private final SettingDetailMapper settingDetailMapper;
    private final CommandIssuedMapper commandIssuedMapper;
    private final CommandExecuteService commandExecuteService;
    private final OperationDetailMapper operationDetailMapper;
    private final OperationVoCacheService operationVoCacheService;
    private final BasicStepSettingsMapper basicStepSettingsMapper;
    private final CommandBoardInfoService commandBoardInfoService;
    private final CommandFirstDataService commandFirstDataService;
    private final CommandOperationService commandOperationService;

    @Override
    public void issued(StepSettingsIssuedSingleReq req) {
        log.info("设备工步指令下发参数StepSettingsIssuedSingle issued:{}", gson.toJson(req));
        // 指令下发
        var command = new CommandIssuedSuccess();
        command.setInit(req.getCabinetNo(), req.getDoor(), req.getId(), req.getBoardNo(), req.getChannelNo(), NumConstant.INT_ONE);
        try {

            long start = System.currentTimeMillis();
            commandOperationService.updateCache(command, true);

            Thread.sleep(NumConstant.INT_FIVE);

            var currentKey = CaffeineUtil.FIRST_DATA_CURRENT_CACHE_KEY + CabinetNoUtil.getCabinetNo(String.valueOf(Integer.parseInt(command.getReqCabinetNo())));
            var voltageKey = CaffeineUtil.FIRST_DATA_VOLTAGE_CACHE_KEY + CabinetNoUtil.getCabinetNo(String.valueOf(Integer.parseInt(command.getReqCabinetNo())));
            CaffeineUtil.deleteStartWith(currentKey);
            CaffeineUtil.deleteStartWith(voltageKey);
            if (!command.isSingleChannel()) {
                CaffeineUtil.delete(CaffeineUtil.FIRST_DATA_ALL_CACHE_PREFIX + Integer.parseInt(command.getReqCabinetNo()) + "_" + command.getBoardNo() + "_" + command.getChannelNo());
            }
            log.info("设备工步指令下发更新及删除缓存:{}ms-{}", (System.currentTimeMillis() - start), currentKey);

            start = System.currentTimeMillis();
            commandIssued(command, true);

            log.info("下发指令完成耗时:{}ms-{}", (System.currentTimeMillis() - start), gson.toJson(command));
            var cacheKey = CaffeineUtil.getCacheKey(Integer.parseInt(command.getReqCabinetNo()), command.getBoardNo(), command.getChannelNo(), command.getOrder());
            CaffeineUtil.set(CaffeineUtil.CACHE_KEY_COMMAND_FIRST + cacheKey, System.currentTimeMillis(), 50);
        } catch (Exception e) {
            log.error("interrupt issued error:", e);
        }
    }

    @Override
    public void endIssued(StepSettingsIssuedSingleReq req) {
        log.info("interrupt issued:{}", req);
        // 指令下发
        var commandIssued = new CommandIssuedSuccess();
        commandIssued.setInit(req.getCabinetNo(), req.getDoor(), NumConstant.LONG_LT_ZERO, req.getBoardNo(), req.getChannelNo(), NumConstant.INT_LT_TEN);
        try {
            commandOperationService.endUpdateCache(commandIssued);

            endCommandIssued(commandIssued);
        } catch (Exception e) {
            log.error("interrupt issued error:", e);
        }
    }

    @Override
    public void nextIssued(CommandIssuedSuccess command) {
        log.info("执行下一个工步StepSettingsIssued next issued:{}", gson.toJson(command));
        try {
            commandOperationService.updateCache(command, false);
            Thread.sleep(NumConstant.INT_FIVE);

            var currentKey = CaffeineUtil.FIRST_DATA_CURRENT_CACHE_KEY + CabinetNoUtil.getCabinetNo(String.valueOf(Integer.parseInt(command.getReqCabinetNo())));
            var voltageKey = CaffeineUtil.FIRST_DATA_VOLTAGE_CACHE_KEY + CabinetNoUtil.getCabinetNo(String.valueOf(Integer.parseInt(command.getReqCabinetNo())));
            CaffeineUtil.deleteStartWith(currentKey);
            CaffeineUtil.deleteStartWith(voltageKey);
            if (!command.isSingleChannel()) {
                CaffeineUtil.delete(CaffeineUtil.FIRST_DATA_ALL_CACHE_PREFIX + Integer.parseInt(command.getReqCabinetNo()) + "_" + command.getBoardNo() + "_" + command.getChannelNo());
            }

            commandIssued(command, false);

            var cacheKey = CaffeineUtil.getCacheKey(Integer.parseInt(command.getReqCabinetNo()), command.getBoardNo(), command.getChannelNo(), command.getOrder());
            CaffeineUtil.set(CaffeineUtil.CACHE_KEY_COMMAND_FIRST + cacheKey, System.currentTimeMillis(), 50);
        } catch (Exception e) {
            log.error("interrupt issued error:", e);
        }
    }

    @Override
    public void interruptReIssuedOneBoardNo(CommandIssuedSuccess commandIssued, Integer expectedTimeSecond) {
        log.info("interruptReIssuedOneBoardNo issued:{}-expectedTimeSecond:{}", commandIssued, expectedTimeSecond);
        try {
            commandOperationService.interruptReIssuedUpdateCache(commandIssued);

            commandInterruptReIssued(commandIssued, expectedTimeSecond);
        } catch (Exception e) {
            log.error("interruptReIssued issued error:", e);
        }
    }

    @Override
    public void interruptReIssued(CommandIssuedSuccess commandIssued, Integer expectedTimeSecond) {
        log.info("interruptReIssued issued:{}-expectedTimeSecond:{}", commandIssued, expectedTimeSecond);
        try {
            commandOperationService.interruptReIssuedUpdateCache(commandIssued);

            commandInterruptReIssued(commandIssued, expectedTimeSecond);
        } catch (Exception e) {
            log.error("interruptReIssued issued error:", e);
        }
    }

    @Override
    public void onlyIssue(CommandIssuedSuccess commandIssued) {
        log.info("下发结束指令StepSettingsIssued onlyIssue issued:{}", gson.toJson(commandIssued));
        commandOnlyIssue(commandIssued);
    }


    /**
     * 指令下发
     *
     * @param command command参数
     */
    public void commandOnlyIssue(CommandIssuedSuccess command) {
        if (command == null || StringUtils.isAnyBlank(command.getReqCabinetNo()) || command.getBoardNo() == null) {
            log.info("commandOnlyIssue failed,cabinetNo is null");
            throw new IssuedException("20001", "command failed, cabinetNo is null");
        }

        var settingDetail = settingDetailMapper.queryListByStepIdAndSettingOrder(command.getInterruptOrEndStepId(), command.getOrder());
        if (null == settingDetail) {
            //throw new IssuedException("10001", "执行失败, 工步方案不存在");
            log.info("commandOnlyIssue failed,settingDetail is null");
            return;
        }

        //log.info("修改前充电设置：{}", gson.toJson(settingDetail));
        settingDetail.setCurrent(configInit.getStopChargingCurrent());
        settingDetail.setVoltage(configInit.getStopChargingVoltage());
        // log.info("修改充电设置：{}", gson.toJson(settingDetail));

        var commandOutInfo = commandBoardInfoService.getCommandOutInfo(command, false);
        log.info("commandOnlyIssue commandBoardInfoService:{}", gson.toJson(commandOutInfo));

        var cabinetNo = CabinetNoUtil.getCabinetNo(command.getReqCabinetNo());

        // 执行任务
        var settings = new AddSettings();
        settings.setCutOff(settingDetail.getCutOff());
        settings.setSetType(settingDetail.getSetType());
        settings.setCurrent(settingDetail.getCurrent());
        settings.setVoltage(settingDetail.getVoltage());
        settings.setCutOffType(settingDetail.getCutOffType());
        settings.setSettingOrder(settingDetail.getSettingOrder());
        settings.setExpectedTime(settingDetail.getExpectedTime());

        var step = basicStepSettingsMapper.findFirstById(settingDetail.getStepId());
        //log.info("修改前充电设置step：{}", gson.toJson(step));
        if (step == null) {
            throw new IssuedException("10001", "工步方案不存在");
        }
        step.setChargeCurrentLimit(configInit.getChargingCurrentLimitMax());
        step.setChargeVoltageLimit(configInit.getChargingVoltageLimitMax());

        //log.info("修改hou充电设置step：{}", gson.toJson(step));

        var result = commandExecuteService.execute(command, cabinetNo, commandOutInfo, settings, step, null);
        log.info("commandOnlyIssue result,cabinetNo:{},result: {}", cabinetNo, result);
        // 失败
        if (!result) {
            throw new IssuedException("10002", "指令下发失败");
        }
    }


    /**
     * 指令下发
     *
     * @param command command参数
     */
    public void commandIssued(CommandIssuedSuccess command, boolean firstCommand) {
        if (null == command || StringUtils.isBlank(command.getReqCabinetNo()) || null == command.getBoardNo()) {
            log.info("commandIssued failed,cabinetNo is null");
            throw new IssuedException("20001", "command failed, cabinetNo is null");
        }

        long stepId = null != command.getInterruptOrEndStepId() &&
                command.getInterruptOrEndStepId() > NumConstant.LONG_ZERO ?
                command.getInterruptOrEndStepId() :
                command.getStepId();
        var settingDetail = settingDetailMapper.queryListByStepIdAndSettingOrder(stepId, command.getOrder());
        if (null == settingDetail) {
            // 发送事件，检查是否是最后的工步，如果是，则导出分容统计数据表报
            context.publishEvent(new CommandIssuedEndEvent(System.currentTimeMillis(), command));
            //throw new IssuedException("10001", "执行失败, 工步方案不存在");
            log.info("commandIssued failed,执行失败,工步方案详情不存在(或工步已全部完成) stepId:{},order:{}", stepId, command.getOrder());
            return;
        }

        // 如果是搁置指令，则不真正执行指令，静置等待
        if (StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(settingDetail.getSetType())) {
            log.info("执行搁置静置指令,stepId:{},order:{},boardNo:{},channelNo:{}", command.getStepId(), command.getOrder(), command.getBoardNo(), command.getChannelNo());
            // 设置工步方案执行时长
            command.setExpectedTimeSecond(settingDetail.getExpectedTime() * 60);
            // 删除部分不使用数据
            command.setSettings("{}");
            command.setSetType(StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode());
            command.setInterruptOrEndStepId(settingDetail.getInterruptOrEndStepId());

            var commandOutInfos = commandBoardInfoService.getCommandOutInfo(command, firstCommand);
            var cab = Integer.parseInt(command.getReqCabinetNo());
            // 指令下发成功后,判断第一帧上送数据事件
            for (var coi : commandOutInfos) {
                command.setSetType(settingDetail.getSetType());
                command.setInterruptOrEndStepId(command.getStepId());
                command.setExpectedTimeSecond(settingDetail.getExpectedTime() * 60);
                commandFirstDataService.commandFirstData(new CommandFirstDataEvent(command, cab, coi.getBoardAddress(), coi.getCells()));
            }

            // 指令下发成功，发布通知事件，相关缓存及数据更新
            context.publishEvent(new CommandIssuedSuccessEvent(System.currentTimeMillis(), command.getOrder() - NumConstant.INT_ONE, command));

            // 设置全部通道缓存
            if (!command.isSingleChannel()) {
                context.publishEvent(new WholeCommandIssuedEvent(Long.parseLong(command.getReqCabinetNo()), command.getStepId(), command.getOrder()));
            }
            return;
        }

        long start = System.currentTimeMillis();

        var commandOutInfo = commandBoardInfoService.getCommandOutInfo(command, firstCommand);
        log.info("工步执行commandIssued commandBoardInfoService:{}ms-{}", System.currentTimeMillis() - start, gson.toJson(commandOutInfo));

        var cabinetNo = CabinetNoUtil.getCabinetNo(command.getReqCabinetNo());

        // 执行任务
        var settings = new AddSettings();
        settings.setCutOff(settingDetail.getCutOff());
        settings.setSetType(settingDetail.getSetType());
        settings.setCurrent(settingDetail.getCurrent());
        settings.setVoltage(settingDetail.getVoltage());
        settings.setCutOffType(settingDetail.getCutOffType());
        settings.setSettingOrder(settingDetail.getSettingOrder());
        settings.setExpectedTime(settingDetail.getExpectedTime());

        start = System.currentTimeMillis();
        var step = basicStepSettingsMapper.findFirstById(settingDetail.getStepId());
        if (null == step) {
            log.info("commandIssued failed,执行失败, 工步方案不存在 stepId:{}, order:{}", stepId, command.getOrder());
            return;
        }

        var result = commandExecuteService.execute(command, cabinetNo, commandOutInfo, settings, step, null);
        log.info("工步指令下发结果commandIssued result,耗时:{}ms,cabinetNo:{},result:{},command:{}", System.currentTimeMillis() - start, cabinetNo, result, gson.toJson(command));
        // 失败
        if (!result) {
            //throw new IssuedException("10002", "指令下发失败");
            log.info("commandIssued failed,指令下发失败,stepId:{}, order:{},{}", stepId, command.getOrder(), false);
            return;
        }

        // 设置工步方案执行时长
        command.setExpectedTimeSecond(settingDetail.getExpectedTime() * 60);
        // 删除部分不使用数据
        settings.setSettingOrder(null);
        settings.setExpectedTime(null);
        command.setInterruptOrEndStepId(settingDetail.getInterruptOrEndStepId());
        command.setSettings(gson.toJson(settings));
        // 指令下发成功，发布通知事件，相关缓存及数据更新
        context.publishEvent(new CommandIssuedSuccessEvent(System.currentTimeMillis(), command.getOrder() - NumConstant.INT_ONE, command));

        // 设置全部通道缓存
        if (!command.isSingleChannel()) {
            context.publishEvent(new WholeCommandIssuedEvent(Long.parseLong(command.getReqCabinetNo()), command.getStepId(), command.getOrder()));
        }
    }


    /**
     * 指令中断重新下发
     *
     * @param command command参数
     */
    public void commandInterruptReIssued(CommandIssuedSuccess command, Integer expectedTimeSecond) {
        if (null == command || StringUtils.isBlank(command.getReqCabinetNo()) || null == command.getBoardNo()) {
            log.info("commandInterruptReIssued failed,cabinetNo is null");
            throw new IssuedException("20001", "command failed, cabinetNo is null");
        }

        var settingDetail = settingDetailMapper.queryListByStepIdAndSettingOrder(command.getStepId(), command.getOrder());
        if (null == settingDetail) {
            // 发送事件，检查是否是最后的工步，如果是，则导出分容统计数据表报
            context.publishEvent(new CommandIssuedEndEvent(System.currentTimeMillis(), command));
            throw new IssuedException("10001", "执行失败, 工步方案不存在");
        }

        // 如果是搁置指令，则不真正执行指令，静置等待
        if (StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(settingDetail.getSetType())) {
            log.info("commandInterruptReIssued 执行搁置静置指令,stepId:{},order:{},boardNo:{},channelNo:{}", command.getStepId(), command.getOrder(), command.getBoardNo(), command.getChannelNo());
            // 设置工步方案执行时长
            command.setExpectedTimeSecond(expectedTimeSecond);
            // 删除部分不使用数据
            command.setSettings("{}");
            command.setSetType(StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode());
            command.setInterruptOrEndStepId(settingDetail.getInterruptOrEndStepId());

            var commandOutInfos = commandBoardInfoService.getCommandOutInfo(command, false);
            var cab = Integer.parseInt(command.getReqCabinetNo());
            // 指令下发成功后,判断第一帧上送数据事件
            for (var coi : commandOutInfos) {
                command.setSetType(settingDetail.getSetType());
                command.setExpectedTimeSecond(expectedTimeSecond);
                command.setInterruptOrEndStepId(command.getStepId());
                commandFirstDataService.commandFirstData(new CommandFirstDataEvent(command, cab, coi.getBoardAddress(), coi.getCells()));
            }

            // 指令下发成功，发布通知事件，相关缓存及数据更新
            context.publishEvent(new CommandIssuedSuccessEvent(System.currentTimeMillis(), command.getOrder() - NumConstant.INT_ONE, command));
            return;
        }

        var commandOutInfo = commandBoardInfoService.getCommandOutInfo(command, false);
        log.info("commandInterruptReIssued commandBoardInfoService:{}", gson.toJson(commandOutInfo));

        var cabinetNo = CabinetNoUtil.getCabinetNo(command.getReqCabinetNo());

        // 执行任务
        var settings = new AddSettings();
        settings.setCutOff(settingDetail.getCutOff());
        settings.setSetType(settingDetail.getSetType());
        settings.setCurrent(settingDetail.getCurrent());
        settings.setVoltage(settingDetail.getVoltage());
        settings.setCutOffType(settingDetail.getCutOffType());
        settings.setSettingOrder(settingDetail.getSettingOrder());
        settings.setExpectedTime(settingDetail.getExpectedTime());

        var step = basicStepSettingsMapper.findFirstById(settingDetail.getStepId());
        if (null == step) {
            throw new IssuedException("10001", "工步方案不存在");
        }

        var result = commandExecuteService.execute(command, cabinetNo, commandOutInfo, settings, step, expectedTimeSecond);
        log.info("commandInterruptReIssued result,cabinetNo:{},result: {}", cabinetNo, result);
        // 失败
        if (!result) {
            throw new IssuedException("10002", "指令下发失败");
        }

        // 设置工步方案执行时长
        command.setExpectedTimeSecond(expectedTimeSecond);
        // 删除部分不使用数据
        settings.setSettingOrder(null);
        settings.setExpectedTime(null);
        command.setInterruptOrEndStepId(settingDetail.getInterruptOrEndStepId());
        command.setSettings(gson.toJson(settings));
        // 指令下发成功，发布通知事件，相关缓存及数据更新
        context.publishEvent(new CommandIssuedSuccessEvent(System.currentTimeMillis(), command.getOrder() - NumConstant.INT_ONE, command));

        // 设置全部通道缓存
        if (!command.isSingleChannel()) {
            context.publishEvent(new WholeCommandIssuedEvent(Long.parseLong(command.getReqCabinetNo()), command.getStepId(), command.getOrder()));
        }
    }


    /**
     * 终止指令下发
     *
     * @param command command参数
     */
    public void endCommandIssued(CommandIssuedSuccess command) {
        if (null == command || StringUtils.isBlank(command.getReqCabinetNo()) || null == command.getBoardNo()) {
            log.info("interruptCommandIssued failed,cabinetNo is null");
            throw new IssuedException("20001", "interruptCommandIssued failed, cabinetNo is null");
        }

        var cabinetNo = CabinetNoUtil.getCabinetNo(command.getReqCabinetNo());

        var commandOutInfo = commandBoardInfoService.getCommandOutInfo(command, false);
        log.info("interruptCommandIssued commandBoardInfoService:{}", gson.toJson(commandOutInfo));

        var basic = basicStepSettingsMapper.findFirstById(NumConstant.LONG_LT_ZERO);
        if (null == basic) {
            throw new IssuedException("20001", "interruptCommandIssued failed, basic is null");
        }

        List<AddSettings> settingLists = gson.fromJson(basic.getStepSettings(), new TypeToken<List<AddSettings>>() {
        }.getType());

        if (CollectionUtils.isEmpty(settingLists)) {
            throw new IssuedException("20001", "interruptCommandIssued failed, settingLists is empty");
        }

        // 执行任务
        var setting = settingLists.getFirst();
        var settings = new AddSettings();
        settings.setCutOff(setting.getCutOff());
        //settings.setCurrent(setting.getCurrent());
        //settings.setVoltage(setting.getVoltage());

        settings.setCurrent(configInit.getStopChargingCurrent());
        settings.setVoltage(configInit.getStopChargingVoltage());

        settings.setExpectedTime(NumConstant.INT_ZERO);
        settings.setCutOffType(setting.getCutOffType());
        settings.setSettingOrder(NumConstant.INT_SUSPEND);
        settings.setSettingOrder(setting.getSettingOrder());
        settings.setSetType(setting.getSetType());

        var step = basicStepSettingsMapper.findFirstById(NumConstant.LONG_LT_ZERO);
        if (null == step) {
            throw new IssuedException("10001", "工步方案不存在");
        }

        step.setChargeCurrentLimit(configInit.getChargingCurrentLimitMax());
        step.setChargeVoltageLimit(configInit.getChargingVoltageLimitMax());

        var result = commandExecuteService.execute(command, cabinetNo, commandOutInfo, settings, step, null);
        log.info("终止 end command Issued result,cabinetNo:{},result: {}", cabinetNo, result);
        // 失败
        if (!result) {
            throw new IssuedException("10002", "指令下发失败");
        }

        // 设置工步方案执行时长
        command.setExpectedTimeSecond(NumConstant.INT_ZERO);
        //  删除部分不使用数据
        settings.setSettingOrder(null);
        settings.setExpectedTime(null);
        command.setSettings(gson.toJson(settings));
        command.setInterruptOrEndStepId(NumConstant.LONG_ZERO);
        var commandIssued = commandIssuedMapper.findByCommandChannel(CabinetNoUtil.getCabinetNo(command.getReqCabinetNo()), command.getBoardNo(), command.getChannelNo());
        var lastOrder = commandIssued == null ? NumConstant.INT_LT_ZERO : commandIssued.getOrderNo();
        //指令下发成功，发布通知事件，相关缓存及数据更新
        context.publishEvent(new CommandIssuedSuccessEvent(System.currentTimeMillis(), lastOrder, command));

//        //单个通道放电工艺
//        channelStatsService.singleStats(command);
//        // 整体放电工艺
//        channelStatsService.allChannelStats(command);

        // 更新全部通道缓存
        updateAllCache(command);
        // 更新单个通道缓存
        updateSigneCache(command);
    }

    private void updateAllCache(CommandIssuedSuccess command) {
        if (null == command || command.isSingleChannel()) {
            return;
        }

        // 删除全部通道缓存
        var k = CaffeineUtil.CACHE_KEY_COMMAND_OPERATE_ALL + CaffeineUtil.getCacheKey(Integer.parseInt(command.getReqCabinetNo()), 255, 255);
        CaffeineUtil.delete(k);
        // 删除全部
        // 查询全部通道缓存
        var operationDetailList = operationDetailMapper.findDetailNotSingleType(String.valueOf(Integer.parseInt(String.valueOf(command.getReqCabinetNo()))), ServerConstant.SINGLE_TYPE_ALL);
        if (CollectionUtils.isEmpty(operationDetailList)) {
            return;
        }

        for (var od : operationDetailList) {
            var opKey = KeyUtil.commandOperateKey(command.getReqCabinetNo(), od.getBoardAddress(), od.getCellNum());
            var vo = operationVoCacheService.getOperationVo(opKey);

            // 单个通道缓存数据更新
            var cacheKey = Integer.parseInt(command.getReqCabinetNo()) + CaffeineUtil.CACHE_KEY_SYMBOL + od.getBoardAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + od.getCellNum();
            var s = cachePutOrGet.getStatsCache(cacheKey);

            if (vo != null && ServerConstant.START_FLAG_NORMAL == vo.getStartFlag() && s != null && ErrorTypeEnum.EXECUTING.getCode() == s.t) {
                vo.setStartFlag(ServerConstant.START_FLAG_DISABLE);
                vo.setDetailsStepId(NumConstant.LONG_LT_TEN);
                operationVoCacheService.putOperationVo(opKey, vo);
                //log.info("删除全部通道缓存:key:{}-{}", opKey, vo);
            }

            if (s != null && ErrorTypeEnum.EXECUTING.getCode() == s.getT()) {
                s.setT(ErrorTypeEnum.STOP.getCode());
                s.setCty(StepTypeNoEnum.STOP.getCode());
                CaffeineUtil.set(CaffeineUtil.STATS_CACHE_PREFIX + cacheKey, s, 24 * 60 * 60 * 1000);
            }

            // 停止定时任务
            if (vo != null) {
                var key = CaffeineUtil.getCacheKey(Integer.parseInt(command.getReqCabinetNo()), od.getBoardAddress(), od.getCellNum());

                var deleteJobName = JobConstant.JOB_NAME_COMMAND + CaffeineUtil.CACHE_KEY_SYMBOL + key;
                R r = quartzService.deleteCronJob(deleteJobName);
                //log.info("终止删除定时任务 jobName：{} r:{}", deleteJobName, gson.toJson(r));
                if (r == null || !ServerConstant.SUCCESS.equals(r.getCode())) {
                    log.info("终止删除定时任务失败 jobName：{} r:{}", deleteJobName, gson.toJson(r));
                }
            }
        }
    }

    private void updateSigneCache(CommandIssuedSuccess command) {
        if (null == command || !command.isSingleChannel()) {
            return;
        }

        var opKey = KeyUtil.commandOperateKey(command.getReqCabinetNo(), command.getBoardNo(), command.getChannelNo());
        var vo = operationVoCacheService.getOperationVo(opKey);
        if (vo != null && ServerConstant.START_FLAG_NORMAL == vo.getStartFlag()) {
            vo.setStartFlag(ServerConstant.START_FLAG_DISABLE);
            vo.setDetailsStepId(NumConstant.LONG_LT_TEN);
            operationVoCacheService.putOperationVo(opKey, vo);
        }

        // 单个通道缓存数据更新
        var cacheKey = Integer.parseInt(command.getReqCabinetNo()) + CaffeineUtil.CACHE_KEY_SYMBOL + command.getBoardNo() + CaffeineUtil.CACHE_KEY_SYMBOL + command.getChannelNo();

        var s = cachePutOrGet.getStatsCache(cacheKey);
        if (s != null) {
            s.setT(ErrorTypeEnum.STOP.getCode());
            s.setCty(StepTypeNoEnum.STOP.getCode());
            CaffeineUtil.set(CaffeineUtil.STATS_CACHE_PREFIX + cacheKey, s, 24 * 60 * 60 * 1000);
        }

        // 停止定时任务
        if (vo != null) {
            var key = CaffeineUtil.getCacheKey(Integer.parseInt(command.getReqCabinetNo()), command.getBoardNo(), command.getChannelNo());

            var deleteJobName = JobConstant.JOB_NAME_COMMAND + CaffeineUtil.CACHE_KEY_SYMBOL + key;
            R r = quartzService.deleteCronJob(deleteJobName);
            if (r == null || !ServerConstant.SUCCESS.equals(r.getCode())) {
                log.info("单个通道终止删除定时任务失败 jobName：{} r:{}", deleteJobName, r);
            }
        }
    }


    /**
     * 指令中断重新下发
     *
     * @param command command参数
     */
    @Override
    public String getInterruptReIssuedCmd(CommandIssuedSuccess command, Integer expectedTimeSecond) {
        if (null == command || StringUtils.isBlank(command.getReqCabinetNo()) || null == command.getBoardNo()) {
            log.info("getInterruptReIssuedCmd failed,cabinetNo is null");
            return null;
        }

        var settingDetail = settingDetailMapper.queryListByStepIdAndSettingOrder(command.getStepId(), command.getOrder());
        if (null == settingDetail) {
            log.info("getInterruptReIssuedCmd failed,已经是最后的工步 is null");
            return null;
        }

        // 如果是搁置指令，则不真正执行指令，静置等待
        if (StepTypeNoEnum.STEP_TYPE_SL_NUM.getCode().equalsIgnoreCase(settingDetail.getSetType())) {
            log.info("getInterruptReIssuedCmd commandInterruptReIssued 执行搁置静置指令,stepId:{},order:{},boardNo:{},channelNo:{}", command.getStepId(), command.getOrder(), command.getBoardNo(), command.getChannelNo());
            return null;
        }

        var commandOutInfo = commandBoardInfoService.getCommandOutInfo(command, false);
        if (CollectionUtils.isEmpty(commandOutInfo)) {
            log.info("getInterruptReIssuedCmd failed commandOutInfo is null command:{}", gson.toJson(command));
            return null;
        }
        log.info("getInterruptReIssuedCmd commandBoardInfoService:{}", gson.toJson(commandOutInfo));

        var cabinetNo = CabinetNoUtil.getCabinetNo(command.getReqCabinetNo());

        // 执行任务
        var settings = new AddSettings();
        settings.setCutOff(settingDetail.getCutOff());
        settings.setSetType(settingDetail.getSetType());
        settings.setCurrent(settingDetail.getCurrent());
        settings.setVoltage(settingDetail.getVoltage());
        settings.setCutOffType(settingDetail.getCutOffType());
        settings.setSettingOrder(settingDetail.getSettingOrder());
        settings.setExpectedTime(settingDetail.getExpectedTime());

        var step = basicStepSettingsMapper.findFirstById(settingDetail.getStepId());
        if (null == step) {
            log.info("工步方案不存在");
            return null;
        }

        var result = commandExecuteService.getOneCmd(command, cabinetNo, commandOutInfo, settings, step, expectedTimeSecond);
        log.info("getInterruptReIssuedCmd result,cabinetNo:{},expectedTimeSecond[{}],result: {}", cabinetNo, expectedTimeSecond, result);

        return result;
    }
}
